//
//  LocalVideoEditVC.m
//  ViewFilerClipDemo
//
//  Created by peter on 2017/3/28.
//  Copyright © 2017年 Zerdoor. All rights reserved.
//

#import "LocalVideoEditVC.h"
#import "FilterChooseView.h"
#define FilterViewHeight 95
// 视频URL路径
#define KVideoUrlPath   \
[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0]
@interface LocalVideoEditVC ()
{
    UIButton * _filterBegin;
    
    NSURL * _videoUrl;
    
    GPUImageView *filterView;//预览层 view
}
@property (strong, nonatomic) UIImageView *imageView;
@end

@implementation LocalVideoEditVC

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    self.view.backgroundColor = [UIColor  blackColor];
    UIBarButtonItem * rightItem = [[UIBarButtonItem alloc] initWithTitle:@"选取视频" style:UIBarButtonItemStylePlain target:self action:@selector(choose_click)];
    self.navigationItem.rightBarButtonItem = rightItem;
    
    self.imageView = [[UIImageView alloc] init];
    self.imageView.center = self.view.center;
    self.imageView.backgroundColor =[UIColor redColor];
    self.imageView.bounds = CGRectMake(0, 0, 100, 100);
    [self.view addSubview:self.imageView];
    
    [self choose_click];
    
    _filterBegin = [UIButton buttonWithType:0];
    _filterBegin.backgroundColor = [UIColor whiteColor];
    _filterBegin.frame = CGRectMake(0, 0, self.view.frame.size.width/3-20, 40);
    _filterBegin.center = CGPointMake(self.view.frame.size.width/2, self.view.frame.size.height-30);
    _filterBegin.layer.cornerRadius = 10;
    _filterBegin.clipsToBounds = YES;
    _filterBegin.layer.masksToBounds = YES;
    _filterBegin.layer.borderWidth = 2;
    _filterBegin.layer.borderColor = [UIColor orangeColor].CGColor;
    [_filterBegin setTitleColor:[UIColor blackColor] forState:0];
    [_filterBegin setTitle:@"开始合成" forState:0];
    [_filterBegin addTarget:self action:@selector(filterBegin_click) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:_filterBegin];
    
    
    filterView = [[GPUImageView alloc] initWithFrame:CGRectMake(0, self.navigationController.navigationBar.bounds.size.height+20, self.view.frame.size.width, self.view.frame.size.height-(self.navigationController.navigationBar.bounds.size.height+20)-60-FilterViewHeight)];
    filterView.backgroundColor = [UIColor clearColor];
    [self.view addSubview:filterView];
    
    FilterChooseView * chooseView = [[FilterChooseView alloc] initWithFrame:CGRectMake(0, CGRectGetMaxY(filterView.frame), self.view.frame.size.width, FilterViewHeight)];
    chooseView.backback = ^(GPUImageOutput<GPUImageInput> * filter){
        [self choose_callBack:filter];
    };
    [self.view addSubview:chooseView];
}
#pragma mark 选择滤镜
-(void)choose_callBack:(GPUImageOutput<GPUImageInput> *)filter
{
    pixellateFilter = filter;
    if (!_videoUrl) {
        return;
    }
    [movieFile cancelProcessing];
    [movieFile removeAllTargets];
    movieFile = [[GPUImageMovie alloc] initWithURL:_videoUrl];
    
    [movieFile addTarget:pixellateFilter];
    [pixellateFilter addTarget:filterView];
    [movieFile startProcessing];
}
-(void)showVideoWith:(NSURL *)videourl
{
    [movieFile cancelProcessing];
    
    movieFile = [[GPUImageMovie alloc] initWithURL:videourl];
    if (pixellateFilter) {
        [movieFile addTarget:pixellateFilter];
        [pixellateFilter addTarget:filterView];
    }else
    {
        [movieFile addTarget:filterView];
    }
    [movieFile startProcessing];
    [_filterBegin setImage:[self thumbnailImageForVideo:videourl atTime:3] forState:0];
    self.imageView.image = [self thumbnailImageForVideo:videourl atTime:5];
}
#pragma mark 开始合成视频
-(void)filterBegin_click
{
    [MBProgressHUD showMessage:@"正在处理"];
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        
        NSString *fileName = [@"Documents/" stringByAppendingFormat:@"Movie%d.m4v",(int)[[NSDate date] timeIntervalSince1970]];
        pathToMovie = [NSHomeDirectory() stringByAppendingPathComponent:fileName];
        NSURL *movieURL = [NSURL fileURLWithPath:pathToMovie];
        
        AVURLAsset * asss = [AVURLAsset URLAssetWithURL:[self clipUrl] options:nil];
        CGSize videoSize2 = asss.naturalSize;
        NSLog(@"%f    %f",videoSize2.width,videoSize2.height);
        movieWriter = [[GPUImageMovieWriter alloc] initWithMovieURL:movieURL size:videoSize2];
        [pixellateFilter addTarget:movieWriter];
        
        movieWriter.shouldPassthroughAudio = YES;
        //    movieFile.audioEncodingTarget = movieWriter;
        [movieFile enableSynchronizedEncodingUsingMovieWriter:movieWriter];
        [movieWriter startRecording];
        
        __weak LocalVideoEditVC * weakSelf = self;
        __weak GPUImageOutput<GPUImageInput> * weakpixellateFilter = pixellateFilter;
        __weak GPUImageMovieWriter * weakmovieWriter = movieWriter;
        NSLog(@"进度------%.2f",movieFile.progress);
        [movieWriter setCompletionBlock:^{
            NSLog(@"视频合成结束");
            dispatch_async(dispatch_get_main_queue(), ^{
                [MBProgressHUD hideHUD];
                [MBProgressHUD showSuccess:@"处理结束"];
                
                UIAlertView * alertview = [[UIAlertView alloc] initWithTitle:@"是否保存到相册" message:nil delegate:weakSelf cancelButtonTitle:@"取消" otherButtonTitles:@"保存", nil];
                [alertview show];
            });
            [weakpixellateFilter removeTarget:weakmovieWriter];
            [weakmovieWriter finishRecording];
        }];
        
    });
}
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
    if (buttonIndex == 1) {
        NSLog(@"baocun");
        [self save_to_photosAlbum:pathToMovie];
    }
}
-(void)save_to_photosAlbum:(NSString *)path
{
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        if (UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(path)) {
            
            UISaveVideoAtPathToSavedPhotosAlbum(path, self, @selector(video:didFinishSavingWithError:contextInfo:), nil);
        }
    });
    
}
-(void)choose_click
{
    UIAlertController *alertVc = [UIAlertController alertControllerWithTitle:@"选择视频来源" message:@"选择一个视频" preferredStyle:UIAlertControllerStyleAlert];
    
    UIAlertAction *cameraAction = [UIAlertAction actionWithTitle:@"从相机拍摄" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        [self selectImageFromCamera];
        NSLog(@"选取视频 相机");
    }];
    UIAlertAction *photoAction = [UIAlertAction actionWithTitle:@"从相册选取" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        [self selectImageFromAlbum];
        NSLog(@"选取视频 相册");
    }];
    
    UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil];
    [alertVc addAction:cameraAction];
    [alertVc addAction:photoAction];
    [alertVc addAction:cancelAction];
    [self presentViewController:alertVc animated:YES completion:nil];
    
}

/** 采集后的视频路径 */
- (NSURL*)clipUrl {
    NSArray *docPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);
    NSString *documentsPath = [docPath objectAtIndex:0];
    return [NSURL fileURLWithPath:[documentsPath stringByAppendingPathComponent:@"clip.mp4"]];
}


/**
 根据时间获取对应帧的图片

 @param videoURL 视频沙盒路径
 @param time 时间
 */
- (UIImage*) thumbnailImageForVideo:(NSURL *)videoURL atTime:(NSTimeInterval)time {
    AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:videoURL options:nil];
    NSParameterAssert(asset);
    AVAssetImageGenerator *assetImageGenerator = [[AVAssetImageGenerator alloc] initWithAsset:asset];
    assetImageGenerator.appliesPreferredTrackTransform = YES;
    assetImageGenerator.apertureMode = AVAssetImageGeneratorApertureModeEncodedPixels;
    
    CGImageRef thumbnailImageRef = NULL;
    CFTimeInterval thumbnailImageTime = time * asset.duration.timescale;
    NSError *thumbnailImageGenerationError = nil;
    thumbnailImageRef = [assetImageGenerator copyCGImageAtTime:CMTimeMake(thumbnailImageTime, asset.duration.timescale) actualTime:NULL error:&thumbnailImageGenerationError];
    
    if (!thumbnailImageRef)
        NSLog(@"thumbnailImageGenerationError %@", thumbnailImageGenerationError);
    
    UIImage *thumbnailImage = thumbnailImageRef ? [[UIImage alloc] initWithCGImage:thumbnailImageRef] : nil;
    
    
    return thumbnailImage;
}


-(void)selectImageFromCamera
{
    //NSLog(@"相机");
    UIImagePickerController * _imagePickerController = [[UIImagePickerController alloc] init];
    _imagePickerController.delegate = self;
    _imagePickerController.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
    _imagePickerController.allowsEditing = YES;
    _imagePickerController.sourceType = UIImagePickerControllerSourceTypeCamera;
    //录制视频时长，默认10s
    _imagePickerController.videoMaximumDuration = MAXFLOAT;
    //相机类型（拍照、录像...）
    _imagePickerController.mediaTypes = @[(NSString *)kUTTypeMovie,(NSString *)kUTTypeImage];
    //视频上传质量
    _imagePickerController.videoQuality = UIImagePickerControllerQualityTypeHigh;
    //设置摄像头模式（拍照，录制视频）
    _imagePickerController.cameraCaptureMode = UIImagePickerControllerCameraCaptureModeVideo;
    
    [self presentViewController:_imagePickerController animated:YES completion:nil];
    
}
-(void)selectImageFromAlbum
{
    ZYQAssetPickerController *picker = [[ZYQAssetPickerController alloc] init];
    picker.maximumNumberOfSelection = 1;//只选择一个视频
    picker.assetsFilter = [ALAssetsFilter allVideos];
    picker.showEmptyGroups=NO;
    picker.delegate=self;
    picker.selectionFilter = [NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {
        if ([[(ALAsset*)evaluatedObject valueForProperty:ALAssetPropertyType] isEqual:ALAssetTypeVideo]) {
            NSTimeInterval duration = [[(ALAsset*)evaluatedObject valueForProperty:ALAssetPropertyDuration] doubleValue];
            return duration >= 0;
        } else {
            return YES;
        }
    }];
    
    [self presentViewController:picker animated:YES completion:NULL];
}

/** 采集完成 */
- (void)_clipFinished {
    dispatch_async(dispatch_get_main_queue(), ^{
        [self showVideoWith:[self clipUrl]];
    });
}

/** 视频总时长 */
- (CGFloat)_videoSecondes:(AVAsset*)asset {
    return asset.duration.value*1.0f/asset.duration.timescale;
}


//用时间戳对文件命名 到毫秒
-(NSString *)renameWithTimeSp:(NSString *)fileName{
    NSArray *spArr = [fileName componentsSeparatedByString:@"."];
    int hs = arc4random() % 100;
    NSDate *newDate = [NSDate date];
    long int timeSp = (long)[newDate timeIntervalSince1970];
    fileName = [NSString stringWithFormat:@"%ld%d.%@",timeSp,hs,[spArr lastObject]];
    return fileName;
}


/** 剪切 */
- (void)clipWithUrl:(NSString *)clipPath{
    
    /** 如果有剪切后的视频路径，删除后重新创建 */
    if ([[NSFileManager defaultManager] fileExistsAtPath:[[self clipUrl] path]]) {
        NSError *error = nil;
        [[NSFileManager defaultManager] removeItemAtURL:[self clipUrl] error:&error];
        NSLog(@"remove exist file %@",error);
    }
    
    AVMutableComposition *mainComposition = [[AVMutableComposition alloc] init];
    /** 这里视频和声音都要做采集处理 */
    AVMutableCompositionTrack *compositionVideoTrack = [mainComposition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
    AVMutableCompositionTrack *soundtrackTrack = [mainComposition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
    
    CMTime duration = kCMTimeZero;
    AVAsset *asset = [AVAsset assetWithURL:[NSURL fileURLWithPath:clipPath]];
    /** 视频总时长 */
    float videoSecondes = [self _videoSecondes:asset];
    
    /** 采集的范围，从总时长0.3倍开始，采集总时长的0.5倍的时长 */
    CMTimeRange rangeTime = CMTimeRangeMake(CMTimeMakeWithSeconds( videoSecondes*0.1f, asset.duration.timescale), CMTimeMakeWithSeconds( videoSecondes*0.8f, asset.duration.timescale));
    
    /** 视频采集，音频采集范围应一致 */
    [compositionVideoTrack insertTimeRange:rangeTime ofTrack:[asset tracksWithMediaType:AVMediaTypeVideo].firstObject atTime:duration error:nil];
    /** 声音采集，音频采集范围应一致 */
    [soundtrackTrack insertTimeRange:rangeTime ofTrack:[asset tracksWithMediaType:AVMediaTypeAudio].firstObject atTime:duration error:nil];
    
    /** 视频导出类 */
    AVAssetExportSession *exporter = [[AVAssetExportSession alloc] initWithAsset:mainComposition presetName:AVAssetExportPreset1280x720];
    /** 采集后的视频返回的路径 */
    exporter.outputURL = [self clipUrl];
    exporter.outputFileType = AVFileTypeMPEG4;
    exporter.shouldOptimizeForNetworkUse = YES;
    __weak typeof(self) weakSelf = self;
    [exporter exportAsynchronouslyWithCompletionHandler:^{
        dispatch_async(dispatch_get_main_queue(), ^{
            switch (exporter.status) {
                case AVAssetExportSessionStatusWaiting:
                    break;
                case AVAssetExportSessionStatusExporting:
                    break;
                case AVAssetExportSessionStatusCompleted:
                    NSLog(@"exporting completed");
                    // 想做什么事情在这个做
                    _videoUrl = [self clipUrl];
                    [weakSelf _clipFinished];
                    break;
                case AVAssetExportSessionStatusFailed:
                    NSLog(@"error");
                    [MBProgressHUD showError:@"请重试"];
                    break;
                case AVAssetExportSessionStatusUnknown:
                    NSLog(@"Unknown");
                    break;
                default:
                    [weakSelf _clipFinished];
                    NSLog(@"exporting failed %@",[exporter error]);
                    break;
            }

        });
        
    }];
}

// 将原始视频的URL转化为NSData数据,写入沙盒
- (void)videoWithUrl:(NSURL *)url withFileName:(NSString *)fileName
{
    // 解析一下,为什么视频不像图片一样一次性开辟本身大小的内存写入?
    // 想想,如果1个视频有1G多,难道直接开辟1G多的空间大小来写?
    // 创建存放原始图的文件夹--->VideoURL
    NSFileManager * fileManager = [NSFileManager defaultManager];
    if (![fileManager fileExistsAtPath:KVideoUrlPath]) {
        [fileManager createDirectoryAtPath:KVideoUrlPath withIntermediateDirectories:YES attributes:nil error:nil];
    }
    ALAssetsLibrary *assetLibrary = [[ALAssetsLibrary alloc] init];
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        if (url) {
            [assetLibrary assetForURL:url resultBlock:^(ALAsset *asset) {
                ALAssetRepresentation *rep = [asset defaultRepresentation];
                NSString * videoPath = [KVideoUrlPath stringByAppendingPathComponent:fileName];
                const char *cvideoPath = [videoPath UTF8String];
                FILE *file = fopen(cvideoPath, "a+");
                if (file) {
                    const int bufferSize = 11024 * 1024;
                    // 初始化一个1M的buffer
                    Byte *buffer = (Byte*)malloc(bufferSize);
                    NSUInteger read = 0, offset = 0, written = 0;
                    NSError* err = nil;
                    if (rep.size != 0)
                    {
                        do {
                            read = [rep getBytes:buffer fromOffset:offset length:bufferSize error:&err];
                            written = fwrite(buffer, sizeof(char), read, file);
                            offset += read;
                        } while (read != 0 && !err);//没到结尾，没出错，ok继续、
                        NSLog(@"err:%@",err.localizedDescription);
                    }
                    // 释放缓冲区，关闭文件
                    free(buffer);
                    buffer = NULL;
                    fclose(file);
                    file = NULL;
                    
//                    //回到主线程更新UI
//                    dispatch_async(dispatch_get_main_queue(), ^{
//                    });
                }
            } failureBlock:nil];
        }
    });
}

//清空缓存中数据
-(void)cleanCachesVideo{
    NSFileManager * fileManager = [NSFileManager defaultManager];
    if (![fileManager fileExistsAtPath:KVideoUrlPath]) {
        [fileManager createDirectoryAtPath:KVideoUrlPath withIntermediateDirectories:YES attributes:nil error:nil];
    }
    
    NSArray *contents = [fileManager contentsOfDirectoryAtPath:KVideoUrlPath error:NULL];
    NSEnumerator *e = [contents objectEnumerator];
    NSString *filename;
    while ((filename = [e nextObject])) {
        
        /*if ([[filename pathExtension] isEqualToString:@"mp4"] || [[filename pathExtension] isEqualToString:@"mov"] || [[filename pathExtension] isEqualToString:@"MOV"]|| [[filename pathExtension] isEqualToString:@"MP4"]) {
         }*/
        [fileManager removeItemAtPath:[KVideoUrlPath stringByAppendingPathComponent:filename] error:NULL];
    }
}

#pragma mark - ZYQAssetPickerController Delegate
-(void)assetPickerController:(ZYQAssetPickerController *)picker didFinishPickingAssets:(NSArray *)assets{
//    [self cleanCachesVideo];
    for (int i=0; i<assets.count; i++) {
        ALAsset * asset = assets[i];
        NSURL * url = asset.defaultRepresentation.url;
        
        [self videoWithUrl:url withFileName:asset.defaultRepresentation.filename];
        _videoUrl = [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/%@",KVideoUrlPath,asset.defaultRepresentation.filename]];
//        NSLog(@"---%@",[NSString stringWithFormat:@"%@/%@",KVideoUrlPath,asset.defaultRepresentation.filename]);
//        [self clipWithUrl:[NSString stringWithFormat:@"%@/%@",KVideoUrlPath,asset.defaultRepresentation.filename]];
    }
    if (_videoUrl) {
        [self showVideoWith:_videoUrl];
    }
}



#pragma mark UIImagePickerControllerDelegate
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info{
    NSString *mediaType=[info objectForKey:UIImagePickerControllerMediaType];
    
    if ([mediaType isEqualToString:(NSString *)kUTTypeImage]){
        
    }else{
        //如果是视频
        NSURL *url = info[UIImagePickerControllerMediaURL];
        NSLog(@"%@",[url path]);
        _videoUrl = url;
        //保存视频至相册（异步线程）
        NSString *urlStr = [url path];
        
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            if (UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(urlStr)) {
                
                UISaveVideoAtPathToSavedPhotosAlbum(urlStr, self, @selector(video:didFinishSavingWithError:contextInfo:), nil);
            }
        });
    }
    [self dismissViewControllerAnimated:YES completion:^{
        [self showVideoWith:_videoUrl];
    }];
}
#pragma mark 视频保存完毕的回调
- (void)video:(NSString *)videoPath didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextIn {
    if (error) {
        NSLog(@"保存视频过程中发生错误，错误信息:%@",error.localizedDescription);
    }else{
        NSLog(@"视频保存成功.");
        [MBProgressHUD showSuccess:@"视频保存成功"];
        
    }
}

@end
